package format

import (
	"context"
	"fmt"
	"io"
	"os"
	"time"
)

var globalWriter io.Writer = os.Stdout

// SetSQLGlobalWriter .
func SetSQLGlobalWriter(writer io.Writer) {
	globalWriter = writer
}

// LoggerLog .
type LoggerLog struct {
	io.Writer
	Context   context.Context
	LogLevel  LogLevel
	traceID   string
	action    string
	traceFunc func(string)
}

// LogLevel .
type LogLevel uint8

const (
	// LogSilent .
	LogSilent LogLevel = iota + 1
	// LogError .
	LogError
	// LogWarn .
	LogWarn
	// LogInfo .
	LogInfo
)

// LogData .
type LogData struct {
	TraceID   string
	Action    string
	TraceFunc func(string)
}

// NewLogger .
func NewLogger(logLevel LogLevel, data LogData) *LoggerLog {
	return &LoggerLog{
		Writer:    globalWriter,
		LogLevel:  logLevel,
		traceID:   data.TraceID,
		action:    data.Action,
		traceFunc: data.TraceFunc,
	}
}

// Info print info
func (l LoggerLog) Info(msg string) {
	if l.LogLevel >= LogInfo {
		l.Printf(LogInfo, msg)
	}
}

// Warn print error messages
func (l LoggerLog) Warn(msg string) {
	if l.LogLevel >= LogWarn {
		l.Printf(LogWarn, msg)
	}
}

// Error .
func (l LoggerLog) Error(msg string) {
	if l.LogLevel >= LogError {
		l.Printf(LogError, msg)
	}
}

// Trace .
func (l LoggerLog) Trace(msg string) {
	l.Printf(LogSilent, msg)
}

// Printf .
func (l LoggerLog) Printf(level LogLevel, content string) {
	msg := fmt.Sprintf("%s %d %s %s trace_id=%s\n", time.Now().UTC().Format(time.RFC3339), level, l.action, content, l.traceID)
	_, _ = l.Writer.Write([]byte(msg))
}
